import * as step from '@flow-step/step-toolkit'
import process from 'process'
import * as fs from "fs";
import path from "path";
import {execSync} from "node:child_process";
import {getParams, IParams} from './params';
import {getJenkinsCertificate} from "./certificate";
import {copyToTargetBin, processBuildResult, processJenkinsBuildNumber, writeParamsToFile} from './util';
import {polyglot} from "./i18n";

export const IS_LINUX = process.platform === 'linux'
export const IS_X64 = process.arch === 'x64'
const SEP = path.sep

function infoV1(params: IParams) {
    step.infoV1(`PIPELINE_ID=${params.pipelineID}`)
    step.infoV1(`PIPELINE_NAME=${params.pipelineName}`)
    step.infoV1(`BUILD_NUMBER=${params.buildNumber}`)
    step.infoV1(`WORK_SPACE=${params.workSpace}`)
    step.infoV1(`PROJECT_DIR=${params.projectDir}`)
    step.infoV1(`BUILD_JOB_ID=${params.buildJobID}`)
    step.infoV1(`JENKINS_MASTER=${params.jenkinsMaster}`)
    step.infoV1(`JENKINS_JOB=${params.jenkinsJob}`)

    step.debug(`params.params: ${params.params}`)
}

export async function run(params: IParams) {
    infoV1(params);
    const tmpParamsFile = writeParamsToFile(params);

    step.infoV1(polyglot.t("print_the_current_workspace"))
    const lsOutput = execSync('ls -al', {encoding: 'utf8'});
    step.infoV1(lsOutput);
    step.infoV1("")

    step.infoV1(polyglot.t("trigger_parameter_list"))
    // outputs2str -dataFile=/tmp/params -eval=true
    const outputs2strBin = copyToTargetBin(__dirname + SEP + 'outputs2str', path.join(params.workSpace, "outputs2str"));
    const outputs2strBinArgs = [`-dataFile=${tmpParamsFile}`, "-eval=true"]
    step.debug(`exec command: ${outputs2strBin} ${outputs2strBinArgs.join(' ')}`)
    const resultCode = await step.exec.call(outputs2strBin, outputs2strBinArgs, {
        listener: {
            stdoutLine: (line: string) => step.infoV1(line),
            stderrLine: (line: string) => step.warnV1(line)
        }
    })
    if (resultCode !== 0) {
        throw new Error(`outputs2strBin exec failed, exit code: ${resultCode}`)
    }

    step.infoV1("")
    step.infoV1(polyglot.t("start_triggering_task", {jenkinsJob: params.jenkinsJob}))

    // jenkins-cli -m $JENKINS_MASTER -u $JENKINS_USERNAME -p $JENKINS_PASSWORD build --job $JENKINS_JOB --paramsFile /tmp/params
    const jenkinsCliBin = copyToTargetBin(__dirname + SEP + 'jenkins-cli', path.join(params.workSpace, "jenkins-cli"));
    const jenkinsCliArgs = ["-m", params.jenkinsMaster, "-u", params.jenkinsUsername, "-p", params.jenkinsPassword, "build", "--job", params.jenkinsJob, "--paramsFile", tmpParamsFile]
    step.debug(`exec command: ${jenkinsCliBin} ${jenkinsCliArgs.join(' ')}`)

    const jenkinsBuildNumber = execSync(`${jenkinsCliBin} ${jenkinsCliArgs.join(' ')}`).toString();
    const result = processJenkinsBuildNumber(jenkinsBuildNumber, params);
    fs.unlinkSync(tmpParamsFile)
    process.exit(result)
}

export function check(params: IParams) {
    step.infoV1(polyglot.t("start_checking_the_results", {jenkinsJob: params.jenkinsJob, jenkinsBuildNumber: params.jenkinsBuildNumber}))
    step.infoV1(polyglot.t("jenkins_task_log_address", {jenkinsMaster: params.jenkinsMaster, jenkinsJob: params.jenkinsJob, jenkinsBuildNumber: params.jenkinsBuildNumber}))

    const jenkinsCliBin = copyToTargetBin(__dirname + SEP + 'jenkins-cli', path.join(params.workSpace, "jenkins-cli"));
    const jenkinsCliArgs = ["-m", params.jenkinsMaster, "-u", params.jenkinsUsername, "-p", params.jenkinsPassword, "check", "--job", params.jenkinsJob, "--number", params.jenkinsBuildNumber]
    step.debug(`exec command: ${jenkinsCliBin} ${jenkinsCliArgs.join(' ')}`)
    const buildResult = execSync(`${jenkinsCliBin} ${jenkinsCliArgs.join(' ')}`).toString();
    step.infoV1(polyglot.t("current_task_status", {buildResult}))

    const result= processBuildResult(buildResult, params);
    process.exit(result)
}

async function runStep(): Promise<void> {
    // jenkins-cli and outputs2str golang binary support linux/amd64 only now
    if (!IS_LINUX || !IS_X64) {
        throw new Error('JenkinsService supports Linux/amd64 systems only now')
    }

    const params = getParams()
    // 如果配置了 Jenkins 服务连接，则从服务端请求Jenkins 账密
    if (process.env["authType"] === "serviceConnection") {
        const jenkinsCertificate = await getJenkinsCertificate()
        params.jenkinsMaster = jenkinsCertificate.jenkinsMaster
        params.jenkinsUsername = jenkinsCertificate.jenkinsUsername
        params.jenkinsPassword = jenkinsCertificate.jenkinsPassword
    }

    process.chdir(params.projectDir);

    const command = process.env['COMMAND']
    switch (command) {
        case 'RUN':
            await run(params);
            break;
        case 'CHECK':
            check(params);
            break;
        default:
            step.errorV1(polyglot.t("no_valid_command"))
    }
}

runStep()
    .then(function () {
        step.success('run step successfully!')
    })
    .catch(function (err: Error) {
        step.error(err.message)
        process.exit(-1)
    })
